﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;

namespace Gmantis.Controls
{
    internal class MenuItemNonFirstLevel : MenuItemBehavior
    {
        // Methods
        public MenuItemNonFirstLevel(MenuItem item)
            : base(item)
        {
            this.DelayTimer = new DispatcherTimer();
            this.DelayTimer.Interval = new TimeSpan(0, 0, 0, 0, base.MenuItem.Menu.MenuOpenDelay);
            this.DelayTimer.Tick += new EventHandler(this.MouseActionComplete);
        }

        public override MenuItem GetFirstItem()
        {
            return base.GetNextEnabledItem(base.MenuItem.GetParentContainers<MenuItem>(), 0);
        }

        public override MenuItem GetLastItem()
        {
            return base.GetPrevEnabledItem(base.MenuItem.GetParentContainers<MenuItem>(), base.MenuItem.GetParentContainers<MenuItem>().Count - 1);
        }

        public override MenuItem GetNextItem(Orientation orientation)
        {
            MenuItem nextItem;
            switch (orientation)
            {
                case Orientation.Horizontal:
                    if (!base.MenuItem.HasItems)
                    {
                        break;
                    }
                    nextItem = base.GetNextEnabledItem(base.MenuItem.MenuItems, 0);
                    if (nextItem == null)
                    {
                        if (!base.MenuItem.IsSubmenuOpen)
                        {
                            CancelSourceEventArgs e = new CancelSourceEventArgs
                            {
                                Source = base.MenuItem,
                                Cancel = false
                            };
                            base.MenuItem.OnSubmenuOpening(e);
                            return base.MenuItem;
                        }
                        break;
                    }
                    return nextItem;

                default:
                    {
                        if (base.MenuItem.IsSubmenuOpen && base.MenuItem.HasItems)
                        {
                            return (base.GetNextEnabledItem(base.MenuItem.MenuItems, 0) ?? base.MenuItem);
                        }
                        IList<MenuItem> parentContainers = base.MenuItem.GetParentContainers<MenuItem>();
                        return (base.GetNextEnabledItem(parentContainers, (base.MenuItem.Index + 1) % parentContainers.Count) ?? base.MenuItem);
                    }
            }
            nextItem = base.MenuItem.FirstLevelMenu.MenuBehavior.GetNextItem(Orientation.Horizontal);
            if (nextItem.FirstLevelMenu != base.MenuItem.FirstLevelMenu)
            {
                return nextItem;
            }
            return base.MenuItem;
        }

        public override MenuItem GetPrevItem(Orientation orientation)
        {
            switch (orientation)
            {
                case Orientation.Horizontal:
                    {
                        if (!base.MenuItem.IsSubmenuOpen)
                        {
                            if (!base.MenuItem.ParentItem.IsFirstLevel)
                            {
                                return base.MenuItem.ParentItem;
                            }
                            MenuItem prevItem = base.MenuItem.FirstLevelMenu.MenuBehavior.GetPrevItem(Orientation.Horizontal);
                            if (prevItem.FirstLevelMenu != base.MenuItem.FirstLevelMenu)
                            {
                                return prevItem;
                            }
                            return base.MenuItem;
                        }
                        CancelSourceEventArgs e = new CancelSourceEventArgs
                        {
                            Source = base.MenuItem,
                            Cancel = false
                        };
                        base.MenuItem.OnSubmenuClosing(e);
                        return base.MenuItem;
                    }
            }
            if (base.MenuItem.IsSubmenuOpen && base.MenuItem.HasItems)
            {
                return (base.GetPrevEnabledItem(base.MenuItem.MenuItems, base.MenuItem.MenuItems.Count - 1) ?? base.MenuItem);
            }
            IList<MenuItem> parentContainers = base.MenuItem.GetParentContainers<MenuItem>();
            return (base.GetPrevEnabledItem(parentContainers, (base.MenuItem.Index == 0) ? (parentContainers.Count - 1) : (base.MenuItem.Index - 1)) ?? base.MenuItem);
        }

        private void MouseActionComplete(object sender, EventArgs e)
        {
            this.DelayTimer.Stop();
            if (this.IsMouseEnterAction)
            {
                base.MenuItem.CollapseSibling();
                if (base.MenuItem.HasItems)
                {
                    CancelSourceEventArgs args = new CancelSourceEventArgs
                    {
                        Source = base.MenuItem,
                        Cancel = false
                    };
                    base.MenuItem.OnSubmenuOpening(args);
                }
            }
        }

        public override void OnMouseClick(object sender, MouseEventArgs e)
        {
            this.DelayTimer.Stop();
            if (base.MenuItem.HasItems)
            {
                CancelSourceEventArgs args = new CancelSourceEventArgs
                {
                    Source = base.MenuItem,
                    Cancel = false
                };
                base.MenuItem.OnSubmenuOpening(args);
            }
            else
            {
                base.MenuItem.Menu.CloseMenu();
            }
        }

        public override void OnMouseEnter(object sender, MouseEventArgs e)
        {
            base.MenuItem.IsMouseOver = true;
            base.ResetIsSubmenuOpenVisuals(base.MenuItem);
            this.DelayTimer.Stop();
            this.IsMouseEnterAction = true;
            this.DelayTimer.Start();
        }

        public override void OnMouseLeave(object sender, MouseEventArgs e)
        {
            base.MenuItem.IsMouseOver = false;
            this.DelayTimer.Stop();
            this.IsMouseEnterAction = false;
            this.DelayTimer.Start();
        }

        public override void ShowSubItems()
        {
            base.ShowSubItems();
        }

        // Properties
        private DispatcherTimer DelayTimer { get; set; }

        private bool IsMouseEnterAction { get; set; }
    }
}
